package com.syyo.admin.config.security.config;

import com.alibaba.fastjson.JSONObject;
import com.syyo.admin.common.constant.SettingsConstant;
import com.syyo.admin.common.enums.ResultEnum;
import com.syyo.admin.utils.MyStringUtils;
import com.syyo.admin.utils.SpringContextHolder;


import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @author /
 * token过滤器
 */
@Slf4j
public class TokenFilter extends GenericFilterBean {

    private final TokenProvider tokenProvider;
    private final SettingsConstant settingsConstant;


    TokenFilter(TokenProvider tokenProvider, SettingsConstant settingsConstant) {
        this.tokenProvider = tokenProvider;
        this.settingsConstant = settingsConstant;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
            throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String token = resolveToken(httpServletRequest);

        if (MyStringUtils.isNotEmpty(token)) {
            // 获取cors的请求头地址
            String header = httpServletRequest.getHeader("Origin");
            // 演示环境关闭 增删改接口
            if (settingsConstant.getIsDemo()) {
                String method = httpServletRequest.getMethod();
                String methods = "DELETE,PUT,POST";
                if (methods.contains(method)) {
                    inoperableawt(response, header);
                    return;
                }
            }

            if (!tokenProvider.validateToken(token)) {
                expiredToken(response, header);
                return;
            }
            Authentication authentication = tokenProvider.getAuthentication(token);
            // 将token保存到SecurityContext对象里
            SecurityContext context = SecurityContextHolder.getContext();
            context.setAuthentication(authentication);
        }
        filterChain.doFilter(request, response);
    }

    /**
     * 演示环境不能操作
     *
     * @param response
     * @throws IOException
     */
    private void inoperableawt(ServletResponse response, String header) throws IOException {
        JSONObject jsonObject = new JSONObject();
        HttpServletResponse resp = (HttpServletResponse) response;
        resp.setContentType("application/json;charset=utf-8");
        // 添加cors返回请求头,不然会有cors跨域问题
        resp.setHeader("Access-Control-Allow-Origin", header);
        PrintWriter writer = response.getWriter();
        jsonObject.put("code", ResultEnum.E_90009.getCode());
        jsonObject.put("message", ResultEnum.E_90009.getMessage());
        String result = jsonObject.toString();
        writer.write(result);
        writer.close();
    }

    /**
     * token过期或者无效，直接返回 90001
     *
     * @param response
     * @throws IOException
     */
    private void expiredToken(ServletResponse response, String header) throws IOException {
        JSONObject jsonObject = new JSONObject();
        HttpServletResponse resp = (HttpServletResponse) response;
        resp.setContentType("application/json;charset=utf-8");
        // 添加cors返回请求头,不然会有cors跨域问题
        resp.setHeader("Access-Control-Allow-Origin", header);
        PrintWriter writer = response.getWriter();
        jsonObject.put("code", ResultEnum.E_90001.getCode());
        jsonObject.put("message", ResultEnum.E_90001.getMessage());
        String result = jsonObject.toString();
        writer.write(result);
        writer.close();
    }

    private String resolveToken(HttpServletRequest request) {
        SecurityProperties properties = SpringContextHolder.getBean(SecurityProperties.class);
        String bearerToken = request.getHeader(properties.getHeader());
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(properties.getTokenStartWith())) {
            return bearerToken.substring(7);
        }
        return null;
    }
}
